package com.yyplatform.admin.platform.notice.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.modelmapper.ModelMapper;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Service;

import com.yyplatform.admin.infra.utils.DateUtils;
import com.yyplatform.admin.platform.notice.model.dto.SysNoticeDTO;
import com.yyplatform.admin.platform.notice.model.dto.SysNoticeFormDTO;
import com.yyplatform.admin.platform.notice.model.dto.SysNoticeQueryDTO;
import com.yyplatform.admin.platform.notice.model.entity.SysNoticeEntity;
import com.yyplatform.admin.platform.notice.model.entity.SysNoticeUserEntity;
import com.yyplatform.admin.platform.notice.repository.SysNoticeRepository;
import com.yyplatform.admin.platform.notice.repository.SysNoticeUserRepository;
import com.yyplatform.admin.platform.notice.service.SysNoticeService;
import com.yyplatform.admin.platform.role.model.entity.SysUserDeptEntity;
import com.yyplatform.admin.platform.role.model.entity.SysUserEntity;
import com.yyplatform.admin.platform.role.repository.SysUserDeptRepository;
import com.yyplatform.admin.platform.role.repository.SysUserRepository;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author sleepforests@163.com
 * <p>
 * Created on 2024/9/24 22:51
 */
@Service
@AllArgsConstructor
@Slf4j
public class SysNoticeServiceImpl implements SysNoticeService {

    private SysNoticeRepository sysNoticeRepository;
    private SysNoticeUserRepository sysNoticeUserRepository;
    private ModelMapper modelMapper;
    private SysUserRepository sysUserRepository;
    private SysUserDeptRepository sysUserDeptRepository;


    @Override
    public Page<SysNoticeDTO> query(SysNoticeQueryDTO pageQueryDTO) {
        Page<SysNoticeEntity> entityPage =
                sysNoticeRepository.findPage(pageQueryDTO.getTitle(),
                        pageQueryDTO.getSendFlag(),
                        pageQueryDTO.getNoticeType(),
                        pageQueryDTO.getDeleteFlag(),
                        DateUtils.getBeginDate(pageQueryDTO.getCreateTimeArr()),
                        DateUtils.getEndDate(pageQueryDTO.getCreateTimeArr()),
                        pageQueryDTO.getPageRequestOrderByIdDesc());

        List<SysNoticeDTO> list = entityPage.stream().map(e -> modelMapper.map(e, SysNoticeDTO.class)).toList();

        return new PageImpl<>(list, entityPage.getPageable(), entityPage.getTotalElements());

    }

    @Override
    public SysNoticeDTO get(Long id) {
        SysNoticeEntity entity = sysNoticeRepository.getReferenceById(id);


        SysNoticeDTO sysNoticeDTO = modelMapper.map(entity, SysNoticeDTO.class);
        if (entity.getSendAllDept()) {
            sysNoticeDTO.setDeptIds(Collections.emptyList());
        } else {
            sysNoticeDTO.setDeptIds(Arrays.stream(entity.getDeptIds().split(",")).toList());
        }

        return sysNoticeDTO;
    }

    @Override
    public void save(SysNoticeFormDTO sysDeptFormDTO) {
        SysNoticeEntity entity = modelMapper.map(sysDeptFormDTO, SysNoticeEntity.class);

        entity.setDeleteFlag(false);
        entity.setSendFlag(false);

        if (entity.getSendAllDept()) {
            entity.setDeptIds("");
        } else {
            entity.setDeptIds(String.join(",", sysDeptFormDTO.getDeptIds()));
        }

        sysNoticeRepository.save(entity);
    }

    @Override
    public void update(SysNoticeFormDTO sysDeptFormDTO) {
        SysNoticeEntity entity = sysNoticeRepository.getReferenceById(sysDeptFormDTO.getId());

        entity.setTitle(sysDeptFormDTO.getTitle());
        entity.setContent(sysDeptFormDTO.getContent());
        entity.setNoticeType(sysDeptFormDTO.getNoticeType());
        entity.setRemark(sysDeptFormDTO.getRemark());

        if (entity.getSendAllDept()) {
            entity.setDeptIds("");
        } else {
            entity.setDeptIds(String.join(",", sysDeptFormDTO.getDeptIds()));
        }

        entity.setSendAllDept(sysDeptFormDTO.getSendAllDept());


        sysNoticeRepository.save(entity);
    }

    @Override
    public void delete(Long id) {

        SysNoticeEntity entity = sysNoticeRepository.getReferenceById(id);
        entity.setDeleteFlag(true);
        sysNoticeRepository.save(entity);


        List<SysNoticeUserEntity> entityList = sysNoticeUserRepository.findByNoticeId(id);
        for (SysNoticeUserEntity noticeUserEntity : entityList) {
            noticeUserEntity.setDeleteFlag(true);
            sysNoticeUserRepository.save(noticeUserEntity);
        }
    }


    @Override
    public void send(Long id) {
        SysNoticeEntity entity = sysNoticeRepository.getReferenceById(id);
        if (entity.getSendFlag()) {
            log.info("notice has been sent, id is {}", id);
            throw new RuntimeException("通知已发送，无法再次发送。");
        }

        if (entity.getDeleteFlag()) {
            log.info("notice has been deleted, id is {}", id);
            throw new RuntimeException("通知已删除，无法再次发送。");
        }


        if (entity.getSendAllDept()) {
            List<SysUserEntity> userList = sysUserRepository.findAll();

            List<SysNoticeUserEntity> noticeUserEntityList = new ArrayList<>();


            for (SysUserEntity user : userList) {
                SysNoticeUserEntity noticeUserEntity = new SysNoticeUserEntity();
                noticeUserEntity.setNoticeId(id);
                noticeUserEntity.setUserId(user.getId());
                noticeUserEntity.setNoticeType(entity.getNoticeType());
                noticeUserEntity.setTitle(entity.getTitle());
                noticeUserEntity.setDeleteFlag(false);
                noticeUserEntity.setReadFlag(false);


                noticeUserEntityList.add(noticeUserEntity);

            }
            log.info("send notice to all user, notice is {}, userList length is {}", entity,
                    noticeUserEntityList.size());
            sysNoticeUserRepository.saveAll(noticeUserEntityList);

            entity.setSendFlag(true);
            sysNoticeRepository.save(entity);

        } else {
            String deptIds = entity.getDeptIds();
            Set<Long> deptIdSet = Arrays.stream(deptIds.split(",")).map(Long::parseLong).collect(Collectors.toSet());

            Set<Long> userIdSet = new HashSet<>();

            for (Long deptId : deptIdSet) {
                List<SysUserDeptEntity> userList = sysUserDeptRepository.findByDeptId(deptId);
                userIdSet.addAll(userList.stream().map(SysUserDeptEntity::getUserId).collect(Collectors.toSet()));
            }


            List<SysNoticeUserEntity> noticeUserEntityList = new ArrayList<>();
            for (Long userId : userIdSet) {
                SysNoticeUserEntity noticeUserEntity = new SysNoticeUserEntity();
                noticeUserEntity.setNoticeId(id);
                noticeUserEntity.setUserId(userId);
                noticeUserEntity.setNoticeType(entity.getNoticeType());
                noticeUserEntity.setTitle(entity.getTitle());
                noticeUserEntity.setDeleteFlag(false);
                noticeUserEntity.setReadFlag(false);


                noticeUserEntityList.add(noticeUserEntity);
            }

            log.info("send notice to dept user, deptIds is {}, notice is {}, userList length is {}",
                    entity.getDeptIds(), entity, noticeUserEntityList.size());
            sysNoticeUserRepository.saveAll(noticeUserEntityList);

            entity.setSendFlag(true);
            sysNoticeRepository.save(entity);
        }


    }
}
